package hr.tvz.lab.tom.malwaredb.add;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;

import com.raizlabs.android.dbflow.sql.language.Select;

import java.util.Calendar;
import java.util.List;

import hr.tvz.lab.tom.malwaredb.R;
import hr.tvz.lab.tom.malwaredb.entity.MalwareObject;

/**
 * Activity to add and edit MalwareObjects in database.
 */
public class AddActivity extends AppCompatActivity {

    // Elements
    private EditText name;
    private Spinner type;
    private Spinner platform;
    private Spinner sourceLanguage;
    private Spinner fileType;
    private EditText size;
    private EditText author;
    private EditText origin;
    private EditText dateDiscovery;
    private EditText aliases;
    private EditText links;
    private EditText description;

    // Element Values
    private Integer counter;
    private String nameValue;
    private String typeValue;
    private String platformValue;
    private String sourceLanguageValue;
    private String fileTypeValue;
    private Integer sizeValue;
    private String authorValue;
    private String originValue;
    private String dateDiscoveryValue;
    private String aliasesValue;
    private String linksValue;
    private String descriptionValue;

    // Link type
    private Spinner linkType;
    private String linkTypeValue;

    // Placeholder for storing aliases and links, DBFlow won't work with List.
    private String aliasStringList = "";
    private String linkStringList = "";
    private Boolean aliasDefined = false;
    private Boolean linkDefined = false;

    // DatePicker
    private Calendar calendar;
    private DatePickerDialog dateDialog;

    private MalwareObject malwareObject;
    private MalwareObject malwareEdit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);

        // Check if there is parcelable. If there is, apply it to malwareEdit variable.
        try{
            malwareEdit = getIntent().getExtras().getParcelable("malware");
        }
        catch(Exception e){
            malwareEdit = null;
        }

        // Get all elements.
        name = (EditText) findViewById(R.id.editName);
        type = configureSpinner(R.id.spinnerType, R.array.add_type, this);
        platform = configureSpinner(R.id.spinnerPlatform, R.array.add_platform, this);
        sourceLanguage = configureSpinner(R.id.spinnerSourceLanguage, R.array.add_source_language, this);
        fileType = configureSpinner(R.id.spinnerFileType, R.array.add_file_type, this);
        size = (EditText) findViewById(R.id.editSize);
        author = (EditText) findViewById(R.id.editAuthor);
        origin = (EditText) findViewById(R.id.editOrigin);
        dateDiscovery = (EditText) findViewById(R.id.editDiscoveryDate);
        aliases = (EditText) findViewById(R.id.editAliases);
        links = (EditText) findViewById(R.id.editLinks);
        description = (EditText) findViewById(R.id.editDescription);
        linkType = configureSpinner(R.id.spinnerLinkType, R.array.link_type, this);

        // Set values for elements only if editing.
        if(malwareEdit != null){
            name.setText(malwareEdit.getName());
            // Attempt to get values from spinners.
            type.setSelection(((ArrayAdapter) type.getAdapter()).getPosition(malwareEdit.getType()));
            platform.setSelection(((ArrayAdapter) platform.getAdapter()).getPosition(malwareEdit.getPlatform()));
            sourceLanguage.setSelection(((ArrayAdapter) sourceLanguage.getAdapter()).getPosition(malwareEdit.getSourceLanguage()));
            fileType.setSelection(((ArrayAdapter) fileType.getAdapter()).getPosition(malwareEdit.getFileType()));
            size.setText(malwareEdit.getSize().toString());
            author.setText(malwareEdit.getAuthor());
            origin.setText(malwareEdit.getOrigin());
            dateDiscovery.setText(malwareEdit.getDateDiscovery());
            description.setText(malwareEdit.getDescription());
            // If aliases or links exist, define boolean variables.
            aliasStringList = malwareEdit.getAliases();
            if(!aliasStringList.isEmpty()) {
                aliasDefined = true;
            }
            linkStringList = malwareEdit.getLinks();
            if(!linkStringList.isEmpty()) {
                linkDefined = true;
            }
        }

        // DatePicker Setup
        calendar = Calendar.getInstance();
        dateDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                dateDiscovery.setText(
                        String.format("%d", dayOfMonth) + "." +
                                String.format("%d", (monthOfYear + 1)) + "." +
                                String.format("%d", year) + ".");
            }
        }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));

        // Back button
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_add, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // Back button
                setResult(RESULT_CANCELED);
                finish();
                return true;
            case R.id.menu_apply:
                // Get whole list to get the last ID.
                List<MalwareObject> list = new Select().from(MalwareObject.class).queryList();
                // Set counter to last ID + 1.
                counter = !list.isEmpty() ? list.get(list.size() - 1).getId() + 1 : 0;
                // Setting values. If empty, define it as unknown.
                nameValue = name.getText().length() != 0 ? name.getText().toString() : "Unknown";
                typeValue = type.getSelectedItemId() != 0 ? type.getSelectedItem().toString() : "Unspecified";
                platformValue = type.getSelectedItemId() != 0 ? platform.getSelectedItem().toString() : "Unspecified";
                sourceLanguageValue = type.getSelectedItemId() != 0 ? sourceLanguage.getSelectedItem().toString() : "Unspecified";
                fileTypeValue = type.getSelectedItemId() != 0 ? fileType.getSelectedItem().toString() : "Unspecified";
                sizeValue = size.getText().length() != 0 ? Integer.parseInt(size.getText().toString()) : 0;
                authorValue = author.getText().length() != 0 ? author.getText().toString() : "Unknown";
                originValue = origin.getText().length() != 0 ? origin.getText().toString() : "Unknown";
                dateDiscoveryValue = dateDiscovery.getText().length() != 0 ? dateDiscovery.getText().toString() : "Unknown";
                aliasesValue = aliasDefined ? aliasStringList : "None;";
                linksValue = linkDefined ? linkStringList : "None|none";
                descriptionValue = description.getText().length() != 0 ? description.getText().toString() : "No description available.";

                // If editing, set ID from object that's being edited. ID is primary key, which should overwrite existing entry on save.
                if(malwareEdit != null){
                    counter = malwareEdit.getId();
                }
                malwareObject = new MalwareObject(counter, nameValue, typeValue, platformValue, sourceLanguageValue, fileTypeValue, sizeValue, authorValue, originValue, dateDiscoveryValue, aliasesValue, linksValue, descriptionValue);
                malwareObject.save();

                // Go back, hopefully added or edited.
                setResult(RESULT_OK);
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Shows date picker.
     * @param v View
     */
    public void onClickSetDiscoveryDate(View v) {
        dateDialog.show();
    }

    /**
     * Adds alias to string list. (Sample: Alias1;Alias2;...AliasN;)
     * @param v View
     */
    public void onClickAddAlias(View v) {
        aliasDefined = true;
        aliasStringList += aliases.getText() + ";";
        aliases.setText("");
    }

    /**
     * Adds link to link list. (Sample: Link1|link;Video2|media;Image3|media...UrlN|link(or media);)
     * If it's link, add |link after URL, |media for media content.
     * @param v
     */
    public void onClickAddLink(View v) {
        linkDefined = true;
        switch ((int) linkType.getSelectedItemId()) {
            case 0:
                linkTypeValue = "link";
                break;
            case 1:
                linkTypeValue = "media";
                break;
            default:
                break;
        }
        linkStringList += links.getText() + "|" + linkTypeValue + ";";
        links.setText("");
    }

    /**
     * Simplified spinner configuration.
     * @param idSpinner Spinner ID
     * @param idArray Array ID
     * @param activity Current activity (this)
     * @return Configured spinner.
     */
    private Spinner configureSpinner(int idSpinner, int idArray, Activity activity) {
        Spinner spinner = (Spinner) activity.findViewById(idSpinner);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(activity, idArray, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        return spinner;
    }
}
